import java.awt.Dimension;
import java.awt.Graphics;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Calendar;

import javax.swing.JComboBox;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JLabel;


public class DatePicker extends JPanel {

	private final int width = 203;
	private final int height = 20;
	
	private ArrayList<Integer> yearChoices;
	private ArrayList<Integer> monthChoices;
	private ArrayList<String> monthWordChoices;
	private ArrayList<Integer> dayChoices;
	
	private JComboBox<Integer> comboBoxYear;
	private JComboBox<String> comboBoxMonth;
	private JComboBox<Integer> comboBoxDay;
	
	final static String WORD_JAN = "JAN";
	final static String WORD_FEB = "FEB";
	final static String WORD_MAR = "MAR";
	final static String WORD_APR = "APR";
	final static String WORD_MAY = "MAY";
	final static String WORD_JUN = "JUN";
	final static String WORD_JUL = "JUL";
	final static String WORD_AUG = "AUG";
	final static String WORD_SEP = "SEP";
	final static String WORD_OCT = "OCT";
	final static String WORD_NOV = "NOV";
	final static String WORD_DEC = "DEC";

	
	public DatePicker(int x, int y)
	{
		//First inits and bounds
		comboBoxYear = new JComboBox<Integer>();
		comboBoxYear.setBounds(0, 0, 70, 20);
		comboBoxMonth = new JComboBox<String>();
		comboBoxMonth.setBounds(80, 0, 60, 20);
		comboBoxDay = new JComboBox<Integer>();
		comboBoxDay.setBounds(150, 0, 50, 20);
		
		//Init choices
		initComboBoxYearChoices();
		initComboBoxMonthChoices();
		initComboBoxDayChoices(2013, Calendar.JANUARY);
		setComboBoxChoicesToCurrentDate();
		setLayout(null);
		
		
		//Action Listeners
		DatePickerActionListener dpActionListener = new DatePickerActionListener();
		comboBoxYear.addActionListener(dpActionListener);
		comboBoxMonth.addActionListener(dpActionListener);
		comboBoxDay.addActionListener(dpActionListener);
		
		//Add to JPanel
		add(comboBoxYear);
		add(comboBoxMonth);
		add(comboBoxDay);
		
		//JPanel settings
		setOpaque(false);
		setBounds(x, y, width, height);
	}
	
	private void setComboBoxChoicesToCurrentDate()
	{
		Calendar calendar = Calendar.getInstance();
		comboBoxYear.setSelectedItem(calendar.get(Calendar.YEAR));
		comboBoxMonth.setSelectedItem(convertMonthToWord(calendar.get(Calendar.MONTH)));
		comboBoxDay.setSelectedItem(calendar.get(Calendar.DAY_OF_MONTH));
	}
	
	private void initComboBoxYearChoices()
	{	
		yearChoices = new ArrayList<Integer>();
		for(int i=1990;i<2100;i++)
			yearChoices.add(i);
		
		comboBoxYear.removeAllItems();
		for(int i=0;i<yearChoices.size();i++)
			comboBoxYear.addItem(yearChoices.get(i));
	}
	
	private void initComboBoxMonthChoices()
	{
		monthChoices = new ArrayList<Integer>();
		for(int i= Calendar.JANUARY;i<=Calendar.DECEMBER;i++)
			monthChoices.add(i);
		
		monthWordChoices = new ArrayList<String>();
		for(int i=0;i<monthChoices.size();i++)
			monthWordChoices.add(convertMonthToWord(monthChoices.get(i)));
		
		comboBoxMonth.removeAllItems();
		for(int i=0;i<monthChoices.size();i++)
			comboBoxMonth.addItem(monthWordChoices.get(i));
	}	
	
	private void initComboBoxDayChoices(int year, int month)
	{
		dayChoices = new ArrayList<Integer>();
		int numDays = getNumDays(year, month);
		for(int i=1;i<=numDays;i++)
			dayChoices.add(i);
		
		comboBoxDay.removeAllItems();
		for(int i=0;i<dayChoices.size();i++)
			comboBoxDay.addItem(dayChoices.get(i));
	}
	
	private int getNumDays(int year, int month)
	{
		switch(month)
		{
			case Calendar.JANUARY: 
			case Calendar.MARCH:
			case Calendar.MAY:
			case Calendar.JULY:
			case Calendar.AUGUST:
			case Calendar.OCTOBER:
			case Calendar.DECEMBER:
				return 31;
				
			case Calendar.APRIL:
			case Calendar.JUNE:
			case Calendar.SEPTEMBER:
			case Calendar.NOVEMBER:
				return 30;
				
			case Calendar.FEBRUARY:
				if(isLeapYear(year))
					return 29;
				else
					return 28;
				
		}
		return 0;
	}
	
	private String convertMonthToWord(int month)
	{
		switch(month)
		{
		case Calendar.JANUARY: return WORD_JAN;
		case Calendar.FEBRUARY: return WORD_FEB;
		case Calendar.MARCH: return WORD_MAR;
		case Calendar.APRIL: return WORD_APR;
		case Calendar.MAY: return WORD_MAY;
		case Calendar.JUNE: return WORD_JUN;
		case Calendar.JULY: return WORD_JUL;
		case Calendar.AUGUST: return WORD_AUG;
		case Calendar.SEPTEMBER: return WORD_SEP;
		case Calendar.OCTOBER: return WORD_OCT;
		case Calendar.NOVEMBER: return WORD_NOV;
		case Calendar.DECEMBER: return WORD_DEC;
		}
		return "";
	}
	
	private int convertWordToMonth(String word)
	{
		if(word.equals(WORD_JAN))
			return Calendar.JANUARY;
		if(word.equals(WORD_FEB))
			return Calendar.FEBRUARY;
		if(word.equals(WORD_MAR))
			return Calendar.MARCH;
		if(word.equals(WORD_APR))
			return Calendar.APRIL;
		if(word.equals(WORD_MAY))
			return Calendar.MAY;
		if(word.equals(WORD_JUN))
			return Calendar.JUNE;
		if(word.equals(WORD_JUL))
			return Calendar.JULY;
		if(word.equals(WORD_AUG))
			return Calendar.AUGUST;
		if(word.equals(WORD_SEP))
			return Calendar.SEPTEMBER;
		if(word.equals(WORD_OCT))
			return Calendar.OCTOBER;
		if(word.equals(WORD_NOV))
			return Calendar.NOVEMBER;
		if(word.equals(WORD_DEC))
			return Calendar.DECEMBER;
		return -1;
	}
	
	public boolean isLeapYear(int year)
	{
		return year%4 ==0 && (year%100 != 0 || year%400 == 0);
	}
	
	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Dimension size = new Dimension(width, height);
		setPreferredSize(size);
		setMinimumSize(size);
		setMaximumSize(size);
		setSize(size);

		comboBoxYear.paintComponents(g);
		comboBoxMonth.paintComponents(g);
		comboBoxDay.paintComponents(g);
	 }
	
	private int getYear()
	{
		return Integer.parseInt(comboBoxYear.getSelectedItem().toString());
	}

	private int getMonth()
	{
		return convertWordToMonth(comboBoxMonth.getSelectedItem().toString());
	}
	
	private int getDay()
	{
		return Integer.parseInt(comboBoxDay.getSelectedItem().toString());
	}
	
	public Date getDate()
	{
		return Date.valueOf(getYear()+"-"+(getMonth()+1)+"-"+getDay());
	}
	
	public void setDate(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		comboBoxYear.setSelectedItem(calendar.get(Calendar.YEAR));
		comboBoxMonth.setSelectedItem(convertMonthToWord(calendar.get(Calendar.MONTH)));
		comboBoxDay.setSelectedItem(calendar.get(Calendar.DAY_OF_MONTH));
	}
	
	class DatePickerActionListener implements ActionListener
	{

		@Override
		public void actionPerformed(ActionEvent e)
		{
			if(e.getSource() == comboBoxYear && !isAnyComboBoxEmpty())
			{
				if( getMonth() == Calendar.FEBRUARY)
				{
					int previousDay = getDay();
					initComboBoxDayChoices(getYear(), getMonth());
					if(dayChoices.contains(previousDay))
						comboBoxDay.setSelectedItem(previousDay); //this asks for an index
				}
				
			}
			else if(e.getSource() == comboBoxMonth && !isAnyComboBoxEmpty())
			{
				int previousDay = getDay();
				initComboBoxDayChoices(getYear(), getMonth());
				if(dayChoices.contains(previousDay))
					comboBoxDay.setSelectedItem(previousDay); //this asks for an index
			}
			
		}
		
		private boolean isAnyComboBoxEmpty()
		{
			return comboBoxYear.getSelectedItem() == null || comboBoxMonth.getSelectedItem() == null || comboBoxDay.getSelectedItem() == null;
		}
		
	}
}
